from django.shortcuts import render, redirect
from django.http import JsonResponse
from social.models import UserInform
from music.models import (
    MusicRating,
    MusicComment,
    HotMusic,
    UserFavoriteMusic,
    MusicDetails,
    MusicGenre)
from accounts.models import UserAccount
import numpy as np


def index(request):
    user_info = request.session.get('info', {})
    user_id = user_info.get('id')
    if user_id:
        try:
            user_account = UserAccount.objects.get(id=user_id)
            username = user_account.username
        except UserAccount.DoesNotExist:
            pass
    hotmusics = HotMusic.objects.all()
    musicgenres = MusicGenre.objects.all()
    context = {
        'hotmusics': hotmusics,
        'musicgenres': musicgenres,
        'user_id': user_id,
        'username': username
    }
    return render(request, 'music_index.html', context=context)


def detail(request, music_id):
    # 音乐详情
    music = MusicDetails.objects.get(id=music_id)
    comments = MusicComment.objects.filter(music_id=music_id)
    user_info = request.session.get('info', {})
    user_id = user_info.get('id')

    if user_id:
        try:
            user_account = UserAccount.objects.get(id=user_id)
            username = user_account.username
        except UserAccount.DoesNotExist:
            pass
        flag_mask = MusicRating.objects.filter(
            music_id=music_id, user_id=user_id).first()
    else:
        flag_mask = False
    # 增加浏览量
    music.play_count += 1
    music.save()

    context = {
        'music': music,
        'comments': comments,
        'flag_mask': flag_mask,
        'user_id': user_id,
        'username': username
    }
    print(context)

    return render(request, 'music_detail.html', context=context)


def list_by_category(request, category_id):
    # 音乐分类列表
    user_info = request.session.get('info', {})
    user_id = user_info.get('id')
    if user_id:
        try:
            user_account = UserAccount.objects.get(id=user_id)
            username = user_account.username
        except UserAccount.DoesNotExist:
            pass
    musics = MusicDetails.objects.filter(
        genre_id=category_id
    )
    context = {
        'musics': musics,
        'user_id': user_id,
        'username': username
    }
    return render(request, 'music_list.html', context=context)


def add_like(request):
    # 添加收藏
    music_id = request.POST.get('music_id')
    user_info = request.session.get('info', {})
    user_id = user_info.get('id')
    flag = UserFavoriteMusic.objects.filter(
        music_id=music_id,
        user_id=user_id
    ).first()
    if flag:
        return JsonResponse({'code': 400, 'message': '您已添加，请勿重复添加'})
    UserFavoriteMusic.objects.create(
        user_id=user_id,
        music_id=music_id
    )

    return JsonResponse({'code': 200})


def view_my_likes(request):
    # 我的收藏
    user_info = request.session.get('info', {})
    user_id = user_info.get('id')
    if user_id:
        try:
            user_account = UserAccount.objects.get(id=user_id)
            username = user_account.username
        except UserAccount.DoesNotExist:
            pass
    user_info = request.session.get('info', {})
    user_id = user_info.get('id')
    likes = UserFavoriteMusic.objects.filter(user_id=user_id)
    context = {
        'likes': likes,
        'user_id': user_id,
        'username': username
    }
    return render(request, 'my_like.html', context=context)


def delete_like(request):
    # 删除收藏
    like_id = request.POST.get('like_id')
    UserFavoriteMusic.objects.get(id=like_id).delete()
    return JsonResponse({'code': 200})


def view_top_music(request):
    if request.method == 'GET':
        return render(request, 'top_view.html')
    else:
        musics = MusicDetails.objects.all()
        name_list = []
        count_list = []
        for music in musics:
            name_list.append(music.music_name)
            count_list.append(music.play_count)
        return JsonResponse({'code': 200,
                             'name_list': name_list,
                             'count_list': count_list})


def add_comment(request):
    # 添加评论
    user_info = request.session.get('info', {})
    user_id = user_info.get('id')
    if not user_id:
        return JsonResponse({'code': 400, 'message': '请先登录'})
    content = request.POST.get('content')
    music_id = request.POST.get('music_id')
    if not content:
        return JsonResponse({'code': 400, 'message': '内容不能为空'})
    MusicComment.objects.create(
        id=user_id,
        comment_content=content,
        music_id=music_id
    )
    return JsonResponse({'code': 200})


def calculate_cosine_similarity(user_ratings1, user_ratings2):
    # 将用户1的音乐评分存入字典，键为音乐ID，值为评分
    item_ratings1 = {
        rating.music_id: rating.rating_score for rating in user_ratings1}
    # 将用户2的音乐评分存入字典，键为音乐ID，值为评分
    item_ratings2 = {
        rating.music_id: rating.rating_score for rating in user_ratings2}

    # 找出两个用户共同评价过的音乐
    common_items = set(item_ratings1.keys()) & set(item_ratings2.keys())

    if len(common_items) == 0:
        return 0.0  # 无共同评价的音乐，相似度为0

    # 提取共同评价音乐的评分，存入NumPy数组
    user1_scores = np.array([item_ratings1[music_id]
                            for music_id in common_items])
    user2_scores = np.array([item_ratings2[music_id]
                            for music_id in common_items])

    # 计算余弦相似度
    cosine_similarity = np.dot(user1_scores, user2_scores) / (
        np.linalg.norm(user1_scores) * np.linalg.norm(user2_scores))
    return cosine_similarity


def recommend_for_user(request, user_id):
    user_info = request.session.get('info', {})
    user_id = user_info.get('id')
    if user_id:
        try:
            user_account = UserAccount.objects.get(id=user_id)
            username = user_account.username
        except UserAccount.DoesNotExist:
            pass
    try:
        # 获取目标用户对象
        target_user = UserInform.objects.get(id=user_id)
    except UserInform.DoesNotExist:
        return JsonResponse({'code': 400, 'message': '该用户不存在'})

    # 获取目标用户的音乐评分记录
    target_user_ratings = MusicRating.objects.filter(user=target_user)

    # 用于存储推荐音乐的字典
    recommended_items = {}

    # 遍历除目标用户外的所有其他用户
    for other_user in UserInform.objects.exclude(pk=user_id):
        # 获取其他用户的音乐评分记录
        other_user_ratings = MusicRating.objects.filter(user=other_user)

        # 计算目标用户与其他用户的相似度
        similarity = calculate_cosine_similarity(
            target_user_ratings, other_user_ratings)

        if similarity > 0:
            # 遍历其他用户评价的音乐
            for item_rating in other_user_ratings:
                # 仅考虑目标用户未评价过的音乐
                if item_rating.music not in target_user_ratings.values_list('music', flat=True):
                    if item_rating.music.id in recommended_items:
                        # 累积相似度加权的评分和相似度
                        recommended_items[item_rating.music.id]['score'] += similarity * \
                            item_rating.rating_score
                        recommended_items[item_rating.music.id]['similarity'] += similarity
                    else:
                        # 创建推荐音乐的记录
                        recommended_items[item_rating.music.id] = {'score': similarity * item_rating.rating_score,
                                                                   'similarity': similarity}

    # 将推荐音乐按照加权评分排序
    sorted_recommended_items = sorted(
        recommended_items.items(), key=lambda x: x[1]['score'], reverse=True)

    # 获取排名靠前的推荐音乐的ID
    top_recommended_items = [music_id for music_id,
                             _ in sorted_recommended_items[:4]]

    # 构建响应数据
    response_data = []
    for music_id in top_recommended_items:
        music = MusicDetails.objects.get(pk=music_id)
        similarity = recommended_items[music_id]['similarity']
        response_data.append({
            'name': music.music_name,
            'id': music.id,
            'image': music.cover_image,
            'similarity': similarity,
            'file_url': music.music_file.url
        })
    context = {
        'response_data': response_data,
        'user_id': user_id,
        'username': username
    }
    return render(request, 'music_recommend.html', context=context)


def input_music_score(request):
    # 用户对音乐进行评分
    user_info = request.session.get('info', {})
    user_id = user_info.get('id')
    if not user_id:
        return JsonResponse({'code': 400, 'message': '请先登录'})
    score = int(request.POST.get('score'))
    music_id = request.POST.get('music_id')
    MusicRating.objects.create(
        id=user_id,
        music_id=music_id,
        score=score
    )
    return JsonResponse({'code': 200})
